package org.example.managere.service.impl;

import org.example.managere.dto.CompetingAircraftDTO;
import org.example.managere.entity.operationdata.CompetingAircraft;
import org.example.managere.repository.operationdata.CompetingAircraftRepository;
import org.example.managere.service.CompetingAircraftService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.simple.SimpleJdbcCall;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import jakarta.persistence.criteria.Predicate;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 竞争机型服务实现
 */
@Service
public class CompetingAircraftServiceImpl implements CompetingAircraftService {

    @Autowired
    private CompetingAircraftRepository competingAircraftRepository;
    
    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 构建查询条件
     */
    private Specification<CompetingAircraft> buildSpecification(String keyword) {
        return (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            
            // 关键词搜索
            if (StringUtils.hasText(keyword)) {
                String likePattern = "%" + keyword + "%";
                predicates.add(criteriaBuilder.or(
                    criteriaBuilder.like(root.get("productName"), likePattern),
                    criteriaBuilder.like(root.get("componentReplacementRecord"), likePattern),
                    criteriaBuilder.like(root.get("componentRepairRecord"), likePattern),
                    criteriaBuilder.like(root.get("engineApuReplacementRecord"), likePattern),
                    criteriaBuilder.like(root.get("dailyOperationData"), likePattern),
                    criteriaBuilder.like(root.get("statusChangeRecord"), likePattern),
                    criteriaBuilder.like(root.get("faultReport"), likePattern),
                    criteriaBuilder.like(root.get("operationalInterruptionReport"), likePattern),
                    criteriaBuilder.like(root.get("usageDifficultyReport"), likePattern)
                ));
            }
            
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };
    }

    /**
     * 实体转DTO
     */
    private CompetingAircraftDTO convertToDTO(CompetingAircraft entity) {
        CompetingAircraftDTO dto = new CompetingAircraftDTO();
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }

    /**
     * DTO转实体
     */
    private CompetingAircraft convertToEntity(CompetingAircraftDTO dto) {
        CompetingAircraft entity = new CompetingAircraft();
        BeanUtils.copyProperties(dto, entity);
        return entity;
    }

    @Override
    public Page<CompetingAircraftDTO> findAll(Pageable pageable, String keyword) {
        return competingAircraftRepository.findAll(buildSpecification(keyword), pageable)
                .map(this::convertToDTO);
    }

    @Override
    public Optional<CompetingAircraftDTO> findById(Integer id) {
        return competingAircraftRepository.findById(id)
                .map(this::convertToDTO);
    }
    
    @Override
    public Double calculateAirShutdownRate(String productName) {
        try {
            System.out.println("开始计算产品 '" + productName + "' 的空停率...");
            
            
            // 方法3：使用SimpleJdbcCall（带更多配置）
            try {
                SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                        .withCatalogName("operationdata")  // 指定数据库名
                        .withProcedureName("CalculateAirShutdownRate")  // 保持原始大小写
                        .declareParameters(
                            new org.springframework.jdbc.core.SqlParameter("in_product_name", java.sql.Types.VARCHAR),
                            new org.springframework.jdbc.core.SqlOutParameter("out_air_shutdown_rate", java.sql.Types.DECIMAL)
                        )
                        .withoutProcedureColumnMetaDataAccess();  // 禁用元数据访问，强制使用声明的参数
                
                MapSqlParameterSource paramMap = new MapSqlParameterSource()
                        .addValue("in_product_name", productName);
                
                Map<String, Object> result = jdbcCall.execute(paramMap);
                System.out.println("带更多配置的SimpleJdbcCall执行结果: " + result);
                
                if (result.containsKey("out_air_shutdown_rate")) {
                    Object rate = result.get("out_air_shutdown_rate");
                    
                    if (rate != null) {
                        if (rate instanceof BigDecimal) {
                            return ((BigDecimal) rate).doubleValue();
                        } else if (rate instanceof Double) {
                            return (Double) rate;
                        } else if (rate instanceof Number) {
                            return ((Number) rate).doubleValue();
                        }
                    }
                }
            } catch (Exception e) {
                System.err.println("带更多配置的SimpleJdbcCall方法失败: " + e.getMessage());
            }
            
            // 所有方法都失败了
            System.out.println("所有方法都失败，无法获取空停率");
            return null;
        } catch (Exception e) {
            System.err.println("计算空停率时出现未处理的异常: " + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Double calculateFaultRate(String productName) {
        try {
            System.out.println("开始计算产品 '" + productName + "' 的故障率...");
            
            // 方法3：使用SimpleJdbcCall（带更多配置）
            try {
                SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                        .withCatalogName("operationdata")  // 指定数据库名
                        .withProcedureName("CalculateFaultRate")  // 保持原始大小写
                        .declareParameters(
                            new org.springframework.jdbc.core.SqlParameter("in_product_name", java.sql.Types.VARCHAR),
                            new org.springframework.jdbc.core.SqlOutParameter("out_fault_rate", java.sql.Types.DECIMAL)
                        )
                        .withoutProcedureColumnMetaDataAccess();  // 禁用元数据访问，强制使用声明的参数
                
                MapSqlParameterSource paramMap = new MapSqlParameterSource()
                        .addValue("in_product_name", productName);
                
                Map<String, Object> result = jdbcCall.execute(paramMap);
                System.out.println("故障率计算 - 带更多配置的SimpleJdbcCall执行结果: " + result);
                
                if (result.containsKey("out_fault_rate")) {
                    Object rate = result.get("out_fault_rate");
                    
                    if (rate != null) {
                        if (rate instanceof BigDecimal) {
                            return ((BigDecimal) rate).doubleValue();
                        } else if (rate instanceof Double) {
                            return (Double) rate;
                        } else if (rate instanceof Number) {
                            return ((Number) rate).doubleValue();
                        }
                    }
                }
            } catch (Exception e) {
                System.err.println("故障率计算 - 带更多配置的SimpleJdbcCall方法失败: " + e.getMessage());
            }
            
            // 所有方法都失败了
            System.out.println("所有方法都失败，无法获取故障率");
            return null;
        } catch (Exception e) {
            System.err.println("计算故障率时出现未处理的异常: " + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Double calculateEngineReplacementRate(String productName) {
        try {
            System.out.println("开始计算产品 '" + productName + "' 的发动机拆换率...");
            
            // 使用SimpleJdbcCall（带更多配置）
            try {
                SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                        .withCatalogName("operationdata")  // 指定数据库名
                        .withProcedureName("CalculateEngineReplacementRate")  // 保持原始大小写
                        .declareParameters(
                            new org.springframework.jdbc.core.SqlParameter("in_product_name", java.sql.Types.VARCHAR),
                            new org.springframework.jdbc.core.SqlOutParameter("out_replacement_rate", java.sql.Types.DECIMAL)
                        )
                        .withoutProcedureColumnMetaDataAccess();  // 禁用元数据访问，强制使用声明的参数
                
                MapSqlParameterSource paramMap = new MapSqlParameterSource()
                        .addValue("in_product_name", productName);
                
                Map<String, Object> result = jdbcCall.execute(paramMap);
                System.out.println("发动机拆换率计算 - SimpleJdbcCall执行结果: " + result);
                
                if (result.containsKey("out_replacement_rate")) {
                    Object rate = result.get("out_replacement_rate");
                    System.out.println("获取到发动机拆换率: " + rate + " (类型: " + (rate != null ? rate.getClass().getName() : "null") + ")");
                    
                    if (rate != null) {
                        if (rate instanceof BigDecimal) {
                            return ((BigDecimal) rate).doubleValue();
                        } else if (rate instanceof Double) {
                            return (Double) rate;
                        } else if (rate instanceof Number) {
                            return ((Number) rate).doubleValue();
                        }
                    }
                } else {
                    System.out.println("发动机拆换率计算 - SimpleJdbcCall执行成功但未找到输出参数'out_replacement_rate'");
                }
            } catch (Exception e) {
                System.err.println("发动机拆换率计算 - SimpleJdbcCall方法失败: " + e.getMessage());
                e.printStackTrace();
            }
            
            // 所有方法都失败了
            System.out.println("所有方法都失败，无法获取发动机拆换率");
            return null;
        } catch (Exception e) {
            System.err.println("计算发动机拆换率时出现未处理的异常: " + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Double calculateMTBF(String productName) {
        try {
            System.out.println("开始计算产品 '" + productName + "' 的平均故障间隔时间(MTBF)...");
            
            // 使用SimpleJdbcCall（带更多配置）
            try {
                SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                        .withCatalogName("operationdata")  // 指定数据库名
                        .withProcedureName("CalculateMTBF")  // 保持原始大小写
                        .declareParameters(
                            new org.springframework.jdbc.core.SqlParameter("in_product_name", java.sql.Types.VARCHAR),
                            new org.springframework.jdbc.core.SqlOutParameter("out_mtbf", java.sql.Types.DECIMAL)
                        )
                        .withoutProcedureColumnMetaDataAccess();  // 禁用元数据访问，强制使用声明的参数
                
                MapSqlParameterSource paramMap = new MapSqlParameterSource()
                        .addValue("in_product_name", productName);
                
                Map<String, Object> result = jdbcCall.execute(paramMap);
                System.out.println("MTBF计算 - SimpleJdbcCall执行结果: " + result);
                
                if (result.containsKey("out_mtbf")) {
                    Object mtbf = result.get("out_mtbf");
                    System.out.println("获取到MTBF: " + mtbf + " (类型: " + (mtbf != null ? mtbf.getClass().getName() : "null") + ")");
                    
                    if (mtbf != null) {
                        if (mtbf instanceof BigDecimal) {
                            return ((BigDecimal) mtbf).doubleValue();
                        } else if (mtbf instanceof Double) {
                            return (Double) mtbf;
                        } else if (mtbf instanceof Number) {
                            return ((Number) mtbf).doubleValue();
                        }
                    }
                } else {
                    System.out.println("MTBF计算 - SimpleJdbcCall执行成功但未找到输出参数'out_mtbf'");
                }
            } catch (Exception e) {
                System.err.println("MTBF计算 - SimpleJdbcCall方法失败: " + e.getMessage());
                e.printStackTrace();
            }
            
            // 所有方法都失败了
            System.out.println("所有方法都失败，无法获取MTBF");
            return null;
        } catch (Exception e) {
            System.err.println("计算MTBF时出现未处理的异常: " + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Double calculateReliability(String productName) {
        try {
            System.out.println("开始计算产品 '" + productName + "' 的可靠度...");
            
            // 使用SimpleJdbcCall（带更多配置）
            try {
                SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                        .withCatalogName("operationdata")  // 指定数据库名
                        .withProcedureName("CalculateReliability")  // 保持原始大小写
                        .declareParameters(
                            new org.springframework.jdbc.core.SqlParameter("in_product_name", java.sql.Types.VARCHAR),
                            new org.springframework.jdbc.core.SqlOutParameter("out_reliability", java.sql.Types.DECIMAL)
                        )
                        .withoutProcedureColumnMetaDataAccess();  // 禁用元数据访问，强制使用声明的参数
                
                MapSqlParameterSource paramMap = new MapSqlParameterSource()
                        .addValue("in_product_name", productName);
                
                Map<String, Object> result = jdbcCall.execute(paramMap);
                System.out.println("可靠度计算 - SimpleJdbcCall执行结果: " + result);
                
                if (result.containsKey("out_reliability")) {
                    Object reliability = result.get("out_reliability");
                    System.out.println("获取到可靠度: " + reliability + " (类型: " + (reliability != null ? reliability.getClass().getName() : "null") + ")");
                    
                    if (reliability != null) {
                        if (reliability instanceof BigDecimal) {
                            return ((BigDecimal) reliability).doubleValue();
                        } else if (reliability instanceof Double) {
                            return (Double) reliability;
                        } else if (reliability instanceof Number) {
                            return ((Number) reliability).doubleValue();
                        }
                    }
                } else {
                    System.out.println("可靠度计算 - SimpleJdbcCall执行成功但未找到输出参数'out_reliability'");
                }
            } catch (Exception e) {
                System.err.println("可靠度计算 - SimpleJdbcCall方法失败: " + e.getMessage());
                e.printStackTrace();
            }
            
            // 所有方法都失败了
            System.out.println("所有方法都失败，无法获取可靠度");
            return null;
        } catch (Exception e) {
            System.err.println("计算可靠度时出现未处理的异常: " + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Double calculateMaintenanceFrequency(String productName) {
        try {
            System.out.println("开始计算产品 '" + productName + "' 的维修频率...");
            
            // 使用SimpleJdbcCall（带更多配置）
            try {
                SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                        .withCatalogName("operationdata")  // 指定数据库名
                        .withProcedureName("CalculateMaintenanceFrequency")  // 保持原始大小写
                        .declareParameters(
                            new org.springframework.jdbc.core.SqlParameter("in_product_name", java.sql.Types.VARCHAR),
                            new org.springframework.jdbc.core.SqlOutParameter("out_frequency", java.sql.Types.DECIMAL)
                        )
                        .withoutProcedureColumnMetaDataAccess();  // 禁用元数据访问，强制使用声明的参数
                
                MapSqlParameterSource paramMap = new MapSqlParameterSource()
                        .addValue("in_product_name", productName);
                
                Map<String, Object> result = jdbcCall.execute(paramMap);
                System.out.println("维修频率计算 - SimpleJdbcCall执行结果: " + result);
                
                if (result.containsKey("out_frequency")) {
                    Object frequency = result.get("out_frequency");
                    System.out.println("获取到维修频率: " + frequency + " (类型: " + (frequency != null ? frequency.getClass().getName() : "null") + ")");
                    
                    if (frequency != null) {
                        if (frequency instanceof BigDecimal) {
                            return ((BigDecimal) frequency).doubleValue();
                        } else if (frequency instanceof Double) {
                            return (Double) frequency;
                        } else if (frequency instanceof Number) {
                            return ((Number) frequency).doubleValue();
                        }
                    }
                } else {
                    System.out.println("维修频率计算 - SimpleJdbcCall执行成功但未找到输出参数'out_frequency'");
                }
            } catch (Exception e) {
                System.err.println("维修频率计算 - SimpleJdbcCall方法失败: " + e.getMessage());
                e.printStackTrace();
            }
            
            // 所有方法都失败了
            System.out.println("所有方法都失败，无法获取维修频率");
            return null;
        } catch (Exception e) {
            System.err.println("计算维修频率时出现未处理的异常: " + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    public Double calculateDifficultyReportRate(String productName) {
        try {
            System.out.println("开始计算产品 '" + productName + "' 的使用困难报告频率...");
            
            // 使用SimpleJdbcCall（带更多配置）
            try {
                SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbcTemplate)
                        .withCatalogName("operationdata")  // 指定数据库名
                        .withProcedureName("CalculateDifficultyReportRate")  // 保持原始大小写
                        .declareParameters(
                            new org.springframework.jdbc.core.SqlParameter("in_product_name", java.sql.Types.VARCHAR),
                            new org.springframework.jdbc.core.SqlOutParameter("out_rate", java.sql.Types.DECIMAL)
                        )
                        .withoutProcedureColumnMetaDataAccess();  // 禁用元数据访问，强制使用声明的参数
                
                MapSqlParameterSource paramMap = new MapSqlParameterSource()
                        .addValue("in_product_name", productName);
                
                Map<String, Object> result = jdbcCall.execute(paramMap);
                System.out.println("使用困难报告频率计算 - SimpleJdbcCall执行结果: " + result);
                
                if (result.containsKey("out_rate")) {
                    Object rate = result.get("out_rate");
                    System.out.println("获取到使用困难报告频率: " + rate + " (类型: " + (rate != null ? rate.getClass().getName() : "null") + ")");
                    
                    if (rate != null) {
                        if (rate instanceof BigDecimal) {
                            return ((BigDecimal) rate).doubleValue();
                        } else if (rate instanceof Double) {
                            return (Double) rate;
                        } else if (rate instanceof Number) {
                            return ((Number) rate).doubleValue();
                        }
                    }
                } else {
                    System.out.println("使用困难报告频率计算 - SimpleJdbcCall执行成功但未找到输出参数'out_rate'");
                }
            } catch (Exception e) {
                System.err.println("使用困难报告频率计算 - SimpleJdbcCall方法失败: " + e.getMessage());
                e.printStackTrace();
            }
            
            // 所有方法都失败了
            System.out.println("所有方法都失败，无法获取使用困难报告频率");
            return null;
        } catch (Exception e) {
            System.err.println("计算使用困难报告频率时出现未处理的异常: " + e.getMessage());
            e.printStackTrace();
            throw e;
        }
    }

    @Override
    @Transactional
    public CompetingAircraftDTO save(CompetingAircraftDTO dto) {
        // 设置创建时间
        dto.setCreateTime(LocalDateTime.now());
        dto.setUpdateTime(LocalDateTime.now());
        
        CompetingAircraft entity = convertToEntity(dto);
        entity = competingAircraftRepository.save(entity);
        return convertToDTO(entity);
    }

    @Override
    @Transactional
    public CompetingAircraftDTO update(Integer id, CompetingAircraftDTO dto) {
        // 检查记录是否存在
        CompetingAircraft existing = competingAircraftRepository.findById(id)
                .orElseThrow(() -> new RuntimeException("找不到ID为 " + id + " 的竞争机型记录"));
        
        // 保留原始创建时间
        LocalDateTime createTime = existing.getCreateTime();
        
        // 更新实体属性
        BeanUtils.copyProperties(dto, existing);
        
        // 设置必要字段
        existing.setId(id);
        existing.setCreateTime(createTime);
        existing.setUpdateTime(LocalDateTime.now());
        
        // 保存更新
        existing = competingAircraftRepository.save(existing);
        return convertToDTO(existing);
    }

    @Override
    @Transactional
    public void delete(Integer id) {
        // 检查记录是否存在
        if (!competingAircraftRepository.existsById(id)) {
            throw new RuntimeException("找不到ID为 " + id + " 的竞争机型记录");
        }
        
        competingAircraftRepository.deleteById(id);
    }
} 